package com.supermap.gwfs.datashare.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPReply;

/**
 * 
 * @ClassName: FTPClientFactory 
 * @Description: FTP下载工具类 
 * @author zhoujian
 * @date 2017-6-19
 */
public class FTPClientFactory {

	protected static Logger logger =  Logger.getLogger(FTPClientFactory.class);

	private static final ThreadLocal<FTPClient> threadLocal = new ThreadLocal<FTPClient>();

	public static void main(String[] args) throws IOException {
		// userName="qxtdsybk";
		// password="qxtdsybk08";
		// ip="172.24.176.41";

		String userName = "mnt";
		String password = "123456";
		String ip = "172.24.176.170";
		FTPClient ftpClient = new FTPClient();
		ftpClient.connect(ip);

		System.out.println(ftpClient.login(userName, password));

		System.out.println(ftpClient.printWorkingDirectory());
		BufferedOutputStream buffOut = new BufferedOutputStream(new FileOutputStream("e:/TestAcceptor1.nc"));
		// boolean flag = ftpClient.retrieveFile("/mnt/data/local/ec_thin/2T/20160605/20/0/mos/2016060520_0.nc", buffOut);
		InputStream stream = new FileInputStream(new File("e:/TestAcceptor1.nc"));
		boolean flag = ftpClient.storeFile("/mnt/data/local/ec_thin/2T/20160712/08/0/mos/test111111.nc", stream);
		System.out.println(flag);
		stream.close();
		buffOut.close();
		ftpClient.disconnect();

		// /mnt/data/local/ec_thin/2T/20160605/20/0/mos/2016060520_0.nc
		// /mnt/data/local/ec_thin/2T/20160605/20/0/mos/
	}

	/**
	 * 下载多个文件
	 * @param remoteFileNames 
	 * @param localpath 本地存放的根目录
	 * @return
	 */
	public static boolean loadFile(String remoteFileNames[], String localpath, String ip, String name, String pwd) {
		FTPClient ftpClient = getFtpClient();
		boolean flag = true;
		try {
			if (connectServer(ftpClient, ip, name, pwd)) {
				ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
				ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
				for (String remoteFileName : remoteFileNames) {
					String localFileName = localpath + remoteFileName;
					flag = load(remoteFileName, localFileName, ftpClient);
					if (!flag)
						logger.error(remoteFileName + " loaded failed.");
				}
			}
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		closeConnect();
		return flag;
	}

	/**
	 * 下载单个文件，
	 * @param remoteFileName 远程文件的名
	 * @param localFileName 下载到本地的文件全路径
	 * @param ip
	 * @param name
	 * @param pwd
	 * @return
	 */
	public static boolean loadFile(String remoteFileName, String localFileName, String ip, String name, String pwd) {
		FTPClient ftpClient = getFtpClient();
		boolean flag = true;
		try {
			if (connectServer(ftpClient, ip, name, pwd)) {
				ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
				ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
				flag = load(remoteFileName, localFileName, ftpClient);
				if (!flag)
					logger.error(remoteFileName + " loaded failed.");
			}
			closeConnect();
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		return flag;
	}

	/** 
	* 下载文件 
	 * @param ftpClient 
	* 
	* @param remoteFileName--服务器上的文件名 
	* @param localFileName--本地文件名 
	* @return true 下载成功，false 下载失败 
	*/
	private static boolean load(String remoteFileName, String localFileName, FTPClient ftpClient) {
		boolean flag = true;
		// 下载文件
		BufferedOutputStream buffOut = null;
		try {
			// 新建下载文件夹目录
			createLocalFolder(localFileName);
			buffOut = new BufferedOutputStream(new FileOutputStream(localFileName));
			flag = ftpClient.retrieveFile(remoteFileName, buffOut);
		} catch (Exception e) {
			logger.error(remoteFileName + " loaded failed.", e);
		} finally {
			try {
				if (buffOut != null)
					buffOut.close();
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		return flag;
	}

	private static boolean createLocalFolder(String localFileName) {
		String directory = localFileName.substring(0, localFileName.lastIndexOf("/"));
		String fileName = localFileName.substring(localFileName.lastIndexOf("/") + 1);
		boolean flag = true;
		File f = new File(directory, fileName);
		if (f.exists()) {

		} else {
			// 先创建文件所在的目录
			flag = f.getParentFile().mkdirs();
		}
		return flag;

	}

	/**
	* 创建远程服务器目录
	* 
	* @param remote 远程服务器文件绝对路径
	* @return 目录创建是否成功
	*/
	public static synchronized boolean createDirecroty(String remote, FTPClient ftpClient) {
		try {
			if (ftpClient.changeWorkingDirectory(remote)) {
				// 文件夹存在
			} else {
				// 文件夹不存在,创建目录
				String[] paths = remote.split("/");
				StringBuffer path = new StringBuffer();
				for (String string : paths) {
					path.append(string + "/");
					ftpClient.makeDirectory(path.toString());
				}
				logger.info("Create directory -" + remote + " successful.");
			}
		} catch (IOException e) {
			logger.error("Create directory -" + remote + " failed.");
			logger.error(e.getMessage(), e);
			return false;
		}
		return true;
	}

	/** 
	* 上传单个文件
	* @return true 上传成功，false 上传失败 
	*/
	public static boolean upload(String localFileName, String remoteFileName, FTPClient ftpClient) {

		boolean flag = true;
		InputStream input = null;
		try {
			// 创建ftp目录
			String remotePath = remoteFileName.substring(0, remoteFileName.lastIndexOf("/"));
			FTPClientFactory.createDirecroty(remotePath, ftpClient);

			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
			File file = new File(localFileName);
			input = new FileInputStream(file);
			flag = ftpClient.storeFile(remoteFileName, input);
			if (flag) {
				logger.info(remoteFileName + " 上传成功。。。");
			} else {
				logger.info(remoteFileName + " upload failed ! Check FTP folder permissions, disk space...");
			}
		} catch (IOException e) {
			logger.info("local FileName -" + localFileName + "upload exception , this exception is : ", e);
		} finally {
			if (input != null)
				try {
					input.close();
				} catch (IOException e) {
					logger.error(e.getMessage(), e);
				}
		}
		return flag;

	}

	/**
	 * 
	 * @param localFileName
	 * @param remoteFileName
	 * @param ip
	 * @param name
	 * @param pwd
	 * @return
	 */
	public static boolean uploadFile(String localFileName, String remoteFileName, String ip, String name, String pwd) {
		FTPClient ftpClient = getFtpClient();
		boolean flag = true;
		if (connectServer(ftpClient, ip, name, pwd)) {
			flag = upload(localFileName, remoteFileName, ftpClient);
			if (!flag)
				logger.error(localFileName + " upload fail.");
		}
		closeConnect();
		return flag;
	}

	public static FTPClient getFtpClient() {
		FTPClient ftpClient = threadLocal.get();
		if (ftpClient == null || !ftpClient.isAvailable()) {
			ftpClient = new FTPClient();
			threadLocal.set(ftpClient);
		}
		return ftpClient;
	}

	/** 
	 * 关闭连接 
	 */
	public static void closeConnect() {
		FTPClient ftpClient = threadLocal.get();
		try {
			if (ftpClient != null) {
				ftpClient.logout();
				ftpClient.disconnect();
				threadLocal.remove();
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/** 
	 * 连接到服务器 
	 * 
	 * @return true 连接服务器成功，false 连接服务器失败 
	 * @throws Exception 
	 */
	public static boolean connectServer(FTPClient ftpClient, String ip, String userName, String password) {
		boolean flag = true;
		int reply;
		try {
			// ftpClient.setControlEncoding("GBK");

			ftpClient.configure(getFtpConfig());
			ftpClient.connect(ip);
			ftpClient.login(userName, password);
			ftpClient.configure(new FTPClientConfig(ftpClient.getSystemType()));
			// ftpClient.setDefaultPort(port);

			// 每次数据连接之前，ftp client告诉ftp server开通一个端口来传输数据
			ftpClient.enterLocalPassiveMode();

			reply = ftpClient.getReplyCode();
			ftpClient.setDataTimeout(120000);

			if (!FTPReply.isPositiveCompletion(reply)) {
				ftpClient.disconnect();
				logger.error("Failed to log on to the FTP server, please check! [Server:" + ip + "、" + "User:" + userName + "、" + "Password:" + password);
				logger.debug("FTP Service reject connection ！");
				flag = false;
				// 释放空间
				ftpClient = null;
			}
		} catch (SocketException e) {
			flag = false;
			logger.error("Log on to the FTP server " + ip + " failed,Connection timed out!" + e.getMessage(), e);
		} catch (IOException e) {
			flag = false;
			logger.error("Log on to the FTP server " + ip + " failed,FTP server cannot be opened!" + e.getMessage(), e);
		}
		return flag;
	}

	/** 
	 * 设置FTP客服端的配置--一般可以不设置 
	 * 
	 * @return ftpConfig 
	 */
	private static FTPClientConfig getFtpConfig() {
		FTPClientConfig ftpConfig = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
		ftpConfig.setServerLanguageCode(FTP.DEFAULT_CONTROL_ENCODING);
		return ftpConfig;

	}
}
